package StratelegoGame;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

/**
 * A 2d game board space. The space is capable of storing a game board piece.
 * @author Jace Ferguson
 * @filename GameBoard2DSpace.java
 *
 */
public class GameBoard2DSpace extends JPanel implements GameBoardSpace, MouseInputListener{
	private Dimension spaceSize;
	private Color borderColor;
	private GameBoard2DPiece piece;
	private  Integer id;
	private boolean setable;
	private GameBoard2DLogic observer;
	
	/**
	 * Constructor that creates a space with a 
	 * unique id and gives it a size based on the board.
	 * @param id	Integer	space id
	 * @param size	Dimension 	size of the space
	 */
	public GameBoard2DSpace(Integer id, Dimension size)
	{
		super();
		this.setId(id); //Set the id for the space
		this.setSpaceSize(size);	//set the space size
		this.setable = true;	//Allow the space to be setable by default
		this.borderColor = Color.BLACK;	//Set the border color to black
		this.setBorder(BorderFactory.createLineBorder(this.borderColor));	//create a line border
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));	//Set the layout of the space.
		this.setOpaque(false);	//Make the space transparent except for the border
		this.setObserver(GameBoard2DLogic.getInstance());	//Set the observer to the game logic class
		this.setAlignmentX(JComponent.CENTER_ALIGNMENT);
		this.setAlignmentY(JComponent.CENTER_ALIGNMENT);
		this.addMouseListener(this);	//Add a motion listener to the object for DND and clicking
		this.setTransferHandler(new GameBoard2DPieceTXHandler());	//Set the default DND handler
		this.repaint();	//Repaint the object to reflect changes made.
	}
	
	/**
	 * Add a piece to this space. This method will gladly
	 * over write pieces that exist in the space already.
	 * @return boolean 	successfully added piece
	 */
	public boolean addPieceToSpace(GameBoardPiece piece)
	{
		if(this.getSpaceSetable())
		{
			if(this.piece != null)	//Clear the current piece
				this.removePieceFromSpace();
			this.piece = (GameBoard2DPiece)piece;	//Cast the piece to the 2D one.
			//Make the piece slightly smaller than the space.
			this.piece.setPieceSize(new Dimension(this.spaceSize.width - 6, this.spaceSize.height - 6));
			//Set the piece's space object to the current space.
			this.piece.setSpace(this);
			//Add the component to this component
			this.add((GameBoard2DPiece)piece);
			//Repaint the space to reflect the addition
			this.repaint();
			return true;
		}
		else
		{
			return false;
		}
	}
	
	/**
	 * Reset the color of the border back to black.
	 */
	public void clearHighlight()
	{
		this.setBorder(BorderFactory.createLineBorder(Color.BLACK));
	}
	
	/**
	 * Synonymous with removePieceFromSpace 
	 */
	public void clearSpace()
	{
		this.removePieceFromSpace();
	}
	
	/**
	 * Get the space's integer id.
	 */
	public Integer getId()
	{
		return this.id;
	}
	
	/**
	 * Retrieve the logic observer from the object.
	 * @return	GameBoard2DLogic
	 */
	public GameBoard2DLogic getObserver()
	{
		return this.observer;
	}
	
	/**
	 * Get the piece that is on the object or
	 * null if it has no piece.
	 * @return	GameBoard2DPiece
	 */
	public GameBoard2DPiece getPiece()
	{
		return this.piece;
	}
	
	/**
	 * Get the state of the space's 
	 * setability.
	 */
	public boolean getSpaceSetable()
	{
		return this.setable;
	}
	
	/**
	 * Get the dimensions of the space.
	 * @return	Dimension
	 */
	public Dimension getSpaceSize()
	{
		return this.spaceSize;
	}
	
	/**
	 * Make the border of the space red.
	 */
	public void highlightSpace()
	{
		this.setBorder(BorderFactory.createLineBorder(Color.RED));
	}
	
	/**
	 * Return whether the space has a piece or not.
	 * @return	boolean
	 */
	public boolean isEmpty()
	{
		if(this.piece != null)
		{
			return false;
		}
		return true;
	}
	
	/**
	 * Activate and notify the logic observer
	 * that the space was clicked if the space
	 * is setable.
	 */
	public void mouseClicked(MouseEvent e){
		if(this.setable)
		{
			this.notifyObserver(e);
		}
	}
	public void mouseDragged(MouseEvent e){}
	public void mouseEntered(MouseEvent e){}
	public void mouseExited(MouseEvent e){}
	public void mouseMoved(MouseEvent e){}
	public void mousePressed(MouseEvent e){}
	public void mouseReleased(MouseEvent e){}
	
	/**
	 * Notify logic that a mouseEvent has occurred.
	 * @param e	MouseEvent
	 */
	public void notifyObserver(MouseEvent e)
	{
		if(this.observer != null)
		{
			this.observer.notify(e);
		}
	}
	
	/**
	 * Removes a piece from the space.
	 */
	public void removePieceFromSpace()
	{
		if(this.piece != null)
		{
			//Remove the piece from this space.
			this.remove(this.piece);
			this.piece = null;
			//Repaint to show the change.
			this.repaint();
		}
	}
	
	/**
	 * Set the id for the space.
	 * @param	Integer 
	 */
	public void setId(Integer id)
	{
		this.id = id;
	}
	
	/**
	 * Set another logic observer which gets notified of
	 * mouseEvents
	 * @param observer	GameBoard2DLogic	
	 */
	public void setObserver(GameBoard2DLogic observer)
	{
		this.observer = observer;
	}
	
	/**
	 * Set whether the space is setable or not.
	 * @param	boolean	
	 */
	public void setSpaceSetable(boolean setable)
	{
		this.setable = setable;
	}
	
	/**
	 * Set the size of the space.
	 * @param spaceSize	Dimension	
	 */
	public void setSpaceSize(Dimension spaceSize)
	{
		this.spaceSize = spaceSize;
		//Set component sizes
		this.setPreferredSize(spaceSize);
		this.setMaximumSize(spaceSize);
		this.setMinimumSize(spaceSize);
		//Repaint to reflect changes.
		this.repaint();
	}

}


